# coding: utf-8
import _thread as thread
import os
import time
import base64

import base64
import datetime
import hashlib
import hmac
import json
from urllib.parse import urlparse
import ssl
from datetime import datetime
from time import mktime
from urllib.parse import urlencode
from wsgiref.handlers import format_date_time

import websocket
# import openpyxl
from concurrent.futures import ThreadPoolExecutor, as_completed
import os

from fontTools.misc.cython import returns


class Ws_Param(object):
    # 初始化
    def __init__(self, APPID, APIKey, APISecret, gpt_url):
        self.APPID = APPID
        self.APIKey = APIKey
        self.APISecret = APISecret
        self.host = urlparse(gpt_url).netloc
        self.path = urlparse(gpt_url).path
        self.gpt_url = gpt_url

    # 生成url
    def create_url(self):
        # 生成RFC1123格式的时间戳
        now = datetime.now()
        date = format_date_time(mktime(now.timetuple()))

        # 拼接字符串
        signature_origin = "host: " + self.host + "\n"
        signature_origin += "date: " + date + "\n"
        signature_origin += "GET " + self.path + " HTTP/1.1"

        # 进行hmac-sha256进行加密
        signature_sha = hmac.new(self.APISecret.encode('utf-8'), signature_origin.encode('utf-8'),
                                 digestmod=hashlib.sha256).digest()

        signature_sha_base64 = base64.b64encode(signature_sha).decode(encoding='utf-8')

        authorization_origin = f'api_key="{self.APIKey}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature_sha_base64}"'

        authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')

        # 将请求的鉴权参数组合为字典
        v = {
            "authorization": authorization,
            "date": date,
            "host": self.host
        }
        # 拼接鉴权参数，生成url
        url = self.gpt_url + '?' + urlencode(v)
        # 此处打印出建立连接时候的url,参考本demo的时候可取消上方打印的注释，比对相同参数时生成的url与自己代码生成的url是否一致
        return url


# 收到websocket错误的处理
def on_error(ws, error):
    print("### error:", error)


# 收到websocket关闭的处理
def on_close(ws):
    print("### closed ###")


# 收到websocket连接建立的处理
def on_open(ws):
    thread.start_new_thread(run, (ws,))


def run(ws, *args):
    data = json.dumps(gen_params(appid=ws.appid, query=ws.query, domain=ws.domain))
    ws.send(data)


# 收到websocket消息的处理
def on_message(ws, message):
    data = json.loads(message)
    code = data['header']['code']
    if code != 0:
        print(f'请求错误: {code}, {data}')
        ws.close()
    else:
        choices = data["payload"]["choices"]
        status = choices["status"]
        content = choices["text"][0]["content"]
        ws.response.append(content)  # 将内容追加到 ws.response 中
        if status == 2:
            ws.close()


def gen_params(appid, query, domain):
    """
    通过appid和用户的提问来生成请参数
    """

    data = {
        "header": {
            "app_id": appid,
            "uid": "1234",           
            # "patch_id": []    #接入微调模型，对应服务发布后的resourceid          
        },
        "parameter": {
            "chat": {
                "domain": domain,
                "temperature": 0.5,
                "max_tokens": 4096,
                "auditing": "default",
            }
        },
        "payload": {
            "message": {
                # 如果传入system参数，需要保证第一条是system

                "text": [                {"role": "system", "content": "我需要你帮我分析发给你的新闻内容，然后分析其中的来自北京航空航天大学的主要人物姓名和职务，以及参与的事情，注意不要带上新闻的编辑人员和校外人员，并且如果该人物没有职务则跳过，依次输出每个人物的三个属性：姓名、职务和在新闻中的参与事项，每个人物的属性要分行输出"
                                                                       "例如：\n"
                                                                       "张三\n"
                                                                       "北京航空航天大学校长\n"
                                                                       "在春节期间探访留校学生，并进行慰问\n"
                                                                       "\n"
                                                                       "李四\n"
                                                                       "北京航空航天大学副校长\n"
                                                                       "在春节期间探访留校学生，并进行慰问"},
                    {"role": "user", "content": query}]
            }
        }
    }
    return data


def main(appid, api_secret, api_key, Spark_url, domain, query):
    wsParam = Ws_Param(appid, api_key, api_secret, Spark_url)
    websocket.enableTrace(False)
    wsUrl = wsParam.create_url()

    # 用于存储响应结果
    response = []

    ws = websocket.WebSocketApp(wsUrl, on_message=on_message, on_error=on_error, on_close=on_close, on_open=on_open)
    ws.appid = appid
    ws.query = query
    ws.domain = domain
    ws.response = response
    ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})

    # 在 ws 连接关闭后，返回收集到的消息内容
    return ''.join(ws.response)


def analysis(query):
    test = main(
    appid = "c32bdd5a",
    api_secret = "ZDMxM2NlYWU3NjI3MTEwZmJhZjRmYjMw",
    api_key = "c0511c59c06e6b15ba4cd125ed408970",
    # appid、api_secret、api_key三个服务认证信息请前往开放平台控制台查看（https://console.xfyun.cn/services/bm35）
    Spark_url="wss://spark-api.xf-yun.com/v3.5/chat",      # Max环境的地址
    # Spark_url = "wss://spark-api.xf-yun.com/v4.0/chat",  # 4.0Ultra环境的地址
    # Spark_url = "wss://spark-api.xf-yun.com/v3.1/chat"  # Pro环境的地址
    # Spark_url = "wss://spark-api.xf-yun.com/v1.1/chat",  # Lite环境的地址
    domain="generalv3.5",     # Max版本
    # domain = "4.0Ultra",  # 4.0Ultra 版本


    # domain = "generalv3"    # Pro版本
    # domain = "lite",      # Lite版本址
    query =query
    )
    return test


if __name__ == "__main__":
    print("我需要你帮我分析发给你的新闻内容，然后分析其中的来自北京航空航天大学的主要人物姓名和职务，以及参与的事情，注意不要带上新闻的编辑人员和校外人员，并且如果该人物没有职务则跳过，依次输出每个人物的三个属性：姓名、职务和在新闻中的参与事项，每个人物的属性要分行输出"
                                                                       "例如：\n"
                                                                       "张三\n"
                                                                       "北京航空航天大学校长\n"
                                                                       "在春节期间探访留校学生，并进行慰问\n"
                                                                       "\n"
                                                                       "李四\n"
                                                                       "北京航空航天大学副校长\n"
                                                                       "在春节期间探访留校学生，并进行慰问")

    # test = analysis(
    # "北航新闻网1月2日电（通讯员 刘锐）2019年12月2日，纳米科学权威期刊《ACS Nano》在线发表了我校物理学院微纳物理与应用研究室陈子瑜教授、谢勇副教授及其合作者美国科罗拉多大学博尔德分校Ivan Smalyukhgnetic Nanoparticles within Aerogel Hosts。美国化学会(ACS)旗下的新闻周刊《Chemical & Engineering News》和国内“高分子科学前沿”就相关工作进行了报道。陈子瑜教授的博士生李圆圆为这篇文章的第一家自然科学基金、北京市凝聚态物理学重点学科基金和北航青年拔尖人才等项目的支持。点击图片查看论文原文近年来，航空航天事业蓬勃发展，越来越多的飞行器已进入太空探索浩茫宇宙，甚至于美国国家航天局（）近期已开放国际空间站欢迎普通民众进行太空探索和旅行。但是高昂的发射成本在一定程度上影响着航空航天事业的发展，在目前的技术下，发射1克物体的成本约为1克黄金的价值。气凝胶作为目前已知的最轻固体轻质的固体材料拓展到可操控单元领域正成为当前一个重要且极具价值的研究课题。气凝胶材料本身由于稳定的物理化学性质，使得其对常规外部激励源如光、电、磁、热等无法产生响应，因此其在智能控制单元方面领域的研究积累，由谢勇副教授与博士生李园园尝试开展超轻磁体在智能控制单元方面的探索性研究，通过在气凝胶中掺杂取向的铁磁纳米颗粒获得了具有可编程能力的超轻气凝胶磁性材料——即“空气磁体”。这一设计列，然后通过气凝胶前驱物固化形成的网络结构将铁磁颗粒紧紧束缚，最终，经过临界干燥获得“空气磁体”（见图1）。该制备方法也可以扩展到其他气凝胶和铁磁颗粒系统中，同时其简单、大尺寸的材料制备方法有磁体”的铁磁性来源于其内部的铁磁颗粒，其磁化强度的大小可以通过掺杂铁磁颗粒的浓度进行线性调节。为了展示样品的轻质和铁磁性，研究团队利用一个直径为2cm的环形磁铁实现了磁悬浮。在获得磁操控能力的同)。“空气磁体”内部的磁畴方向是由溶液状态时施加的外部磁场决定的，因此通过设计外部磁场，可以控制“空气磁体”内部的磁畴。当施加非均匀场时，可以实现多畴样品的制备。研究团队以双畴为例，利用两个相反，研究团队设计并展示了磁开关的功能。图3 双畴气凝胶的设计示意图(a-c)，在相反磁场下的磁响应(d, e)，以及相邻处形成的畴壁(f)，磁化曲线测量(g)和磁各向异性测量(h)，最后，通过磁开关展示了其潜在应用展的“空气磁体”将会减少航天航空设备的发射成本，将对航空航天事业的进步产生积极影响。谢勇副教授也曾是陈子瑜教授的博士生，在北航取得博士学位，2014年加入北航物理学院从事教学、科研工作，期间在科罗究组保持着长期合作关系，并推动北航物理学院与该校物理学院签订了国际合作协议。本报道研究成果的部分工作是博士生李圆圆在Smalyukh教授研究组交流期间结合两课题组特色，应用双方优势研究条件完成的。目的多孔纳米材料以用于污水处理和净化。"
    # )
    # print(test)
